package com.itstudio.portal.handle;

import com.itstudio.portal.entity.dto.LoginPasswdDto;
import com.itstudio.portal.enums.HttpCodeEnum;
import com.itstudio.portal.exception.SystemException;
import com.itstudio.portal.utils.Const;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Component
public class MyAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    BCryptPasswordEncoder passwordEncoder;


    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        UserDetails userDetails = null;
        if(authentication.getCredentials() == null){
            LoginPasswdDto login = (LoginPasswdDto)authentication.getPrincipal();
            userDetails = userDetailsService.loadUserByUsername(login.getPhone());
            boolean matches = passwordEncoder.matches(login.getPassword(), userDetails.getPassword());
            if(!matches) throw new SystemException(HttpCodeEnum.PHONE_OR_PASSWORD_ERROR);
        }else{
            String phone = (String) authentication.getPrincipal();
            String code = (String)authentication.getCredentials();
            userDetails = userDetailsService.loadUserByUsername(phone);

            // 从 Redis 获取验证码
            String rCode = redisTemplate.opsForValue().get(Const.LOGIN_CODE + phone);

            // 校验验证码是否匹配
            if (!StringUtils.hasText(rCode) || !rCode.equals(code)) {
                throw new SystemException(HttpCodeEnum.PHONE_OR_CODE_ERROR);
            }
            redisTemplate.delete(Const.LOGIN_CODE + phone);
        }

        return new UsernamePasswordAuthenticationToken(userDetails, null, null);
    }


    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}
